package com.study.demo.ui.thread.list;

import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;

import com.stduy.injector.PerActivity;
import com.study.demo.api.forum.ForumApi;
import com.study.demo.api.game.GameApi;
import com.study.demo.bean.Search;
import com.study.demo.bean.SearchResult;
import com.study.demo.bean.ThreadListResult;
import com.study.demo.components.storage.UserStorage;
import com.study.demo.data.ThreadRepository;
import com.study.demo.db.CustomThread;
import com.study.demo.db.Forum;
import com.study.demo.greendao.ForumDao;
import com.study.demo.util.ToastUtil;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.inject.Inject;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;


/**
 * Created by sll on 2016/3/9.
 */
@PerActivity
public class ThreadListPresenter implements ThreadListContract.Presenter {


    private String fid;
    private ThreadRepository mThreadRepository;
    private GameApi mGameApi;
    private UserStorage mUserStorage;
    private ForumApi mForumApi;
    private ForumDao mForumDao;

    private boolean isFirst = true;
    private PublishSubject<List<CustomThread>> mThreadSubject;
    private ThreadListContract.View mThreadListView;
    private List<CustomThread> customThreads = new ArrayList<>();

    private String lastTid = "";
    private String lastTamp = "";
    private String type;
    private int pageIndex;
    private int loadType = TYPE_LIST;
    private String key;
    private boolean hasNextPage = true;
    private boolean isAttention = false;

    private static final int TYPE_LIST = 1;
    private static final int TYPE_SEARCH = 2;

    private Disposable disposable;

    @Inject
    public ThreadListPresenter(String fid, ThreadRepository mThreadRepository, GameApi mGameApi,
                               UserStorage mUserStorage, ForumApi mForumApi, ForumDao mForumDao) {
        this.fid = fid;
        this.mThreadRepository = mThreadRepository;
        this.mGameApi = mGameApi;
        this.mUserStorage = mUserStorage;
        this.mForumApi = mForumApi;
        this.mForumDao = mForumDao;
        mThreadSubject = PublishSubject.create();
    }

    @Override
    public void onThreadReceive(String type) {
        mThreadListView.showLoading();
        mThreadListView.onFloatingVisibility(View.VISIBLE);
        this.type = type;
        loadType = TYPE_LIST;
        mThreadRepository.getThreadListObservable(Integer.valueOf(fid), mThreadSubject)
                .subscribe(threadList -> {
                            customThreads = threadList;
                            if (customThreads.isEmpty()) {
                                if (!isFirst) {
                                    mThreadListView.onError("数据加载失败");
                                }
                                isFirst = false;
                            } else {
                                mThreadListView.showContent();
                                lastTid = customThreads.get(customThreads.size() - 1).getTid();
                                mThreadListView.renderThreads(customThreads);
                            }
                        }
                );
        loadThreadList("");
        getAttendStatus();
    }

    @Override
    public void onStartSearch(String key, int page) {
        if (TextUtils.isEmpty(key)) {
            mThreadListView.showToast("搜索词不能为空");
            return;
        }
        mThreadListView.showLoading();
        mThreadListView.onFloatingVisibility(View.GONE);
        pageIndex = page;
        this.key = key;
        loadSearchList();
    }

    private void loadThreadList(final String last) {
        disposable = mThreadRepository.getThreadsList(fid, last, lastTamp, type, mThreadSubject)
                .subscribe(threadListData -> {
                    if (threadListData != null && threadListData.result != null) {
                        ThreadListResult data = threadListData.result;
                        lastTamp = data.stamp;
                        hasNextPage = data.nextPage;
                        if (TextUtils.isEmpty(last)) {
                            mThreadListView.onScrollToTop();
                        }
                    }
                    mThreadListView.onRefreshCompleted();
                    mThreadListView.onLoadCompleted(hasNextPage);

                }, throwable -> {
                    if (customThreads.isEmpty()) {
                        mThreadListView.onError("数据加载失败，请重试");
                    } else {
                        mThreadListView.onRefreshCompleted();
                        mThreadListView.onLoadCompleted(hasNextPage);
                        ToastUtil.showToast("数据加载失败，请重试");
                    }
                });
    }

    private void loadSearchList() {
        loadType = TYPE_SEARCH;
        mGameApi.search(key, fid, pageIndex).map(searchData -> {
            if (searchData != null) {
                if (pageIndex == 1) {
                    customThreads.clear();
                }
                SearchResult result = searchData.result;
                hasNextPage = result.hasNextPage == 1;
                for (Search search : result.data) {
                    CustomThread customThread = new CustomThread();
                    customThread.setFid(search.fid);
                    customThread.setTid(search.id);
                    customThread.setLightReply(Integer.valueOf(search.lights));
                    customThread.setReplies(search.replies);
                    customThread.setUserName(search.username);
                    customThread.setTitle(search.title);
                    long time = Long.valueOf(search.addtime);
                    Date date = new Date(time);
                    SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    customThread.setTime(format.format(date));
                    customThreads.add(customThread);
                }
                return customThreads;
            }
            return null;
        }).observeOn(AndroidSchedulers.mainThread()).
                subscribe(threadList -> {
                    if (threadList == null) {
                        loadThreadError();
                    } else {
                        if (threadList.isEmpty()) {
                            mThreadListView.onEmpty();
                        } else {
                            mThreadListView.showContent();
                            mThreadListView.renderThreads(threadList);
                            mThreadListView.onRefreshCompleted();
                            mThreadListView.onLoadCompleted(hasNextPage);
                            if (pageIndex == 1) {
                                mThreadListView.onScrollToTop();
                            }
                        }
                    }
                }, Throwable -> loadThreadError());
    }

    private void loadThreadError() {
        if (customThreads.isEmpty()) {
            mThreadListView.onError("数据加载失败");
        } else {
            mThreadListView.showContent();
            mThreadListView.onRefreshCompleted();
            mThreadListView.onLoadCompleted(true);
            mThreadListView.showToast("数据加载失败");
        }
    }

    private void getAttendStatus() {
        mForumApi.getAttentionStatus(fid)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(attendStatusData -> {
                    if (attendStatusData != null && attendStatusData.status == 200) {
                        mThreadListView.renderThreadInfo(attendStatusData.forumInfo);
                        isAttention = attendStatusData.attendStatus == 1;
                        mThreadListView.attendStatus(isAttention);
                    }

                }, throwable -> getForumInfo());
    }

    private void getForumInfo() {
        Observable.create(
                observableEmitter -> {
                    List<Forum> forumList = mForumDao.queryBuilder().where(ForumDao.Properties.Fid.eq(fid)).list();
                    if (!forumList.isEmpty()) {
                        observableEmitter.onNext(forumList.get(0));
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(forum -> {
                    if (forum instanceof Forum) {
                        if (mThreadListView != null) {
                            mThreadListView.renderThreadInfo((Forum) forum);
                        }
                    }
                });
    }

    @Override
    public void onAttentionClick() {
        if (isLogin()) {
            if (isAttention) {
                delAttention();
            } else {
                addAttention();
            }
        }
    }

    @Override
    public void onPostClick() {
        if (isLogin()) {
            mThreadListView.showPostThreadUi(fid);
        }
    }

    private boolean isLogin() {
        if (!mUserStorage.isLogin()) {
            mThreadListView.showLoginUi();
            return false;
        }
        return true;
    }

    private void addAttention() {
        mForumApi.addAttention(fid)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(attendStatusData -> {
                    if (attendStatusData.status == 200 && attendStatusData.result == 1) {
                        mThreadListView.showToast("添加关注成功");
                        isAttention = attendStatusData.status == 200;
                        mThreadListView.attendStatus(isAttention);
                    }
                }, throwable -> mThreadListView.showToast("添加关注失败，请检查网络后重试"));
    }

    private void delAttention() {
        mForumApi.delAttention(fid)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(attendStatusData -> {
                    if (attendStatusData.status == 200 && attendStatusData.result == 1) {
                        mThreadListView.showToast("取消关注成功");
                        isAttention = attendStatusData.status != 200;
                        mThreadListView.attendStatus(isAttention);
                    }
                }, throwable -> mThreadListView.showToast("取消关注失败，请检查网络后重试"));
    }

    @Override
    public void onRefresh() {
        mThreadListView.onScrollToTop();
        if (loadType == TYPE_LIST) {
            loadThreadList("");
        } else {
            pageIndex = 1;
            loadSearchList();
        }
    }

    @Override
    public void onReload() {
        mThreadListView.showContent();
        mThreadListView.showLoading();
        if (loadType == TYPE_LIST) {
            loadThreadList(lastTid);
        } else {
            loadSearchList();
        }
    }

    @Override
    public void onLoadMore() {
        if (!hasNextPage) {
            mThreadListView.showToast("没有更多了~");
            mThreadListView.onLoadCompleted(false);
            return;
        }

        if (loadType == TYPE_LIST) {
            loadThreadList(lastTid);
        } else {
            pageIndex++;
            loadSearchList();
        }
    }

    @Override
    public void attachView(@NonNull ThreadListContract.View view) {
        mThreadListView = view;
        mThreadListView.showProgress();
    }

    @Override
    public void detachView() {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
        mThreadListView = null;
    }
}
